use macros::gvk;
use serde::{Deserialize, Serialize};


#[derive(Hash)]
#[gvk(
    group = "",
    version = "v1alpha1",
    kind = "Role",
    singular = "role",
    plural = "roles"
)]
pub struct Role {
    pub rules: Vec<PolicyRule>,
}

/// 类型


/// 隐藏的标签
pub static HIDDEN_LABEL_NAME: &str = "halo.run/hidden";

pub static UI_PERMISSIONS_ANNO: &str = "rbac.authorization.halo.run/ui-permissions";
pub static ROLE_AGGREGATE_LABEL_PREFIX: &str = "rbac.authorization.halo.run/aggregate-to-";
/// list dependency
pub static ROLE_DEPENDENCIES_ANNO: &str = "rbac.authorization.halo.run/dependencies";
pub static GROUP: &str = "";


#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)]
pub struct PolicyRule {
    /**
     * APIGroups is the name of the APIGroup that contains the resources.
     * If multiple API groups are specified, any action requested against one of the enumerated
     * resources in any API group will be allowed.
     */
    #[serde(rename = "apiGroups")]
    pub api_groups: Vec<String>,
    /**
     * Resources is a list of resources this rule applies to.  '*' represents all resources in
     * the specified apiGroups.
     * '*&#47;foo' represents the subresource 'foo' for all resources in the specified
     * apiGroups.
     */
    #[serde(rename = "resources")]
    pub resources: Vec<String>,
    /**
     * ResourceNames is an optional white list of names that the rule applies to.  An empty set
     * means that everything is allowed.
     */
    #[serde(rename = "resourceNames")]
    pub resource_names: Vec<String>,
    /**
     * NonResourceURLs is a set of partial urls that a user should have access to.
     * *s are allowed, but only as the full, final step in the path
     * If an action is not a resource API request, then the URL is split on '/' and is checked
     * against the NonResourceURLs to look for a match.
     * Since non-resource URLs are not namespaced, this field is only applicable for
     * ClusterRoles referenced from a ClusterRoleBinding.
     * Rules can either apply to API resources (such as "pods" or "secrets") or non-resource
     * URL paths (such as "/api"),  but not both.
     */
    #[serde(rename = "nonResourceUrls")]
    pub non_resource_urls: Vec<String>,
    /**
     * about who the rule applies to or which namespace the rule applies to.
     */
    #[serde(rename = "verbs")]
    pub verbs: Vec<String>,
}

// impl PartialEq<Self> for PolicyRule {
//     fn eq(&self, other: &Self) -> bool {
//         todo!()
//     }
// }

// impl PartialOrd for PolicyRule {
//     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
//         let mut result = compare(&self.api_groups, &other.api_groups);
//         if result != Equal {
//             return Some(result);
//         }
//         result = compare(&self.resources, &other.resources);
//         if result != Equal {
//             return Some(result);
//         }
//         result = compare(&self.resource_names, &other.resource_names);
//         if result != Equal {
//             return Some(result);
//         }
//         result = compare(&self.non_resource_urls, &other.non_resource_urls);
//         if result != Equal {
//             return Some(result);
//         }
//         return Some(compare(&self.verbs, &other.verbs));
//     }
// }

// fn compare<T: PartialOrd>(a: &[T], b: &[T]) -> Ordering {
//     // 如果两个切片引用的是同一个对象，返回0
//     if a.as_ptr() == b.as_ptr() {
//         return Equal;
//     }
//     // 如果其中一个切片是空的，返回-1或1
//     if a.is_empty() {
//         return if b.is_empty() { Equal } else { Less };
//     }
//     if b.is_empty() {
//         return Greater;
//     }
//     // 比较两个切片的前min(len(a), len(b))个元素
//     for i in 0..std::cmp::min(a.len(), b.len()) {
//         let oa = &a[i];
//         let ob = &b[i];
//         if oa != ob {
//             // 如果元素之一是None，返回-1或1
//             if oa.is_null() || ob.is_null() {
//                 return if oa.is_null() { Less } else { Greater };
//             }
//             // 使用PartialOrd trait来比较元素
//             if oa.cmp(ob) != Equal {
//                 return oa.cmp(ob);
//             }
//         }
//     }
//     // 如果a的长度大于b，返回1；如果b的长度大于a，返回-1；如果长度相等，返回0
//     a.len() as i32 - b.len() as i32
// }


 